#include "tcp_server.hpp"
#include <memory>
#include "Protocol.hpp"
#include <signal.h>
#include "Daemon.hpp"

using namespace ns_tcpserver;
using namespace ns_protocol;

static void Usage(const std::string &process)
{
    std::cout << "\nUsage: " << process << " port\n"
              << std::endl;
}

static Response calculatorHelper(const Request &req)
{
    Response resp(0, 0, req.x_, req.y_, req.op_);
    switch (req.op_)
    {
    case '+':
        resp.result_ = req.x_ + req.y_;
        break;
    case '-':
        resp.result_ = req.x_ - req.y_;
        break;
    case '*':
        resp.result_ = req.x_ * req.y_;
        break;
    case '/':
        if (req.y_ == 0)
            resp.code_ = 1;
        else
            resp.result_ = req.x_ / req.y_;
        break;
    case '%':
        if (req.y_ == 0)
            resp.code_ = 2;
        else
            resp.result_ = req.x_ % req.y_;
        break;
    default:
        resp.code_ = 3;
        break;
    }
    return resp;
}

void calculator(int sock)
{
    std::string inbuffer;
    while (true)
    {
        // 1.读取数据成功
        bool res = Recv(sock, &inbuffer);
        if (!res)
            break;
        // std::cout << "begin: inbuffer" << inbuffer << std::endl;
        // 2.协议解析,获得一个完整报文
        std::string package = Decode(inbuffer);
        if (package.empty())
            continue;
        // std::cout << "end: inbuffer" << inbuffer << std::endl;
        // std::cout << "package" << package << std::endl;

        logMessage(NORMAL, "%s", package.c_str());
        // 3.保证报文是完整的
        Request req;
        // 4.反序列化，字节流-》结构化
        req.Deserialize(package); // 反序列化
        // 5.业务逻辑
        Response resp = calculatorHelper(req);
        // 6.序列化
        std::string respString = resp.Serialize(); // 对计算结果序列化发送到网络
        // 7.添加长度信息
        // std::cout<<"respString: "<<respString<<std::endl;
        respString = EnCode(respString);
        // std::cout<<"encode: respString: "<<respString<<std::endl;
        // 8.
        Send(sock, respString);
    }
}

// void handler(int signo)
// {
//     std::cout<<"get a signo"<<signo<<std::endl;
//     exit(0);
// }

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(1);
    }
    // 一般经验：server在编写的时候，要有较为严谨的判断逻辑
    // 一般服务器，都是要忽略SIGPIPE信号的，防止运行中出现非法写入的情况
    signal(SIGPIPE, SIG_IGN);
    MyDaemon();
    std::unique_ptr<TcpServer> server(new TcpServer(atoi(argv[1])));
    server->BindService(calculator);
    
    server->Start();

    // Request req(123,456,'+');
    // std::string s=req.Serialize();
    // std::cout<<s<<std::endl;

    // Request temp;
    // temp.Deserialize(s);
    // std::cout<<temp.x_<<std::endl;
    // std::cout<<temp.op_<<std::endl;
    // std::cout<<temp.y_<<std::endl;

    return 0;
}